package com.music.glide.util

import java.io.FilterInputStream
import java.io.IOException
import java.io.InputStream
import kotlin.math.max

class KContentLengthInputStream(
    private val inputStream: InputStream, private val contentLength: Long
) : FilterInputStream(inputStream) {

    private var readSoFar = 0

    @Synchronized
    @Throws(IOException::class)
    override fun available(): Int {
        return max((contentLength - readSoFar).toInt(), inputStream.available())
    }

    override fun read(): Int {
        val value = super.read()
        checkReadSoFarOrThrow(value)
        return value;
    }

    @Synchronized
    override fun read(b: ByteArray?, off: Int, len: Int): Int {
        return checkReadSoFarOrThrow(super.read(b, off, len))
    }

    @Throws(IOException::class)
    private fun checkReadSoFarOrThrow(read:Int):Int {
        if (read >= 0) {
            readSoFar += read
        } else if (contentLength - readSoFar > 0) {
            throw IOException("Failed to read all expected data , expected:${contentLength},but read:${readSoFar}")
        }
        return read
    }


    companion object {
        private const val TAG = "ContentLengthStream"
        private const val UNKNOWN = -1L

        fun obtain(other: InputStream, contentLength: String): InputStream {
            return obtain(
                other, kotlin.runCatching { contentLength.toLong() }.getOrNull() ?: UNKNOWN
            )
        }

        fun obtain(other: InputStream, contentLength: Long): InputStream {
            return KContentLengthInputStream(other, contentLength)
        }
    }
}